package com.linx.rxdata

import io.reactivex.Observable
import io.reactivex.subjects.BehaviorSubject

open class RxCollectionData<T>(private val list: MutableCollection<T>) : MutableCollection<T> by list {

    private val subject = BehaviorSubject.create<Collection<T>>().also {
        it.onNext(this)
    }

    private var emitted = false

    open fun observe(): Observable<out Collection<T>> {
        return subject
    }

    override fun remove(element: T): Boolean {
        return wrap {
            list.remove(element)
        }
    }

    override fun add(element: T): Boolean {
        return wrap {
            list.add(element)
        }
    }

    override fun addAll(elements: Collection<T>): Boolean {
        return wrap {
            list.addAll(elements)
        }
    }

    override fun removeAll(elements: Collection<T>): Boolean {
        return wrap {
            list.removeAll(elements)
        }
    }

    override fun retainAll(elements: Collection<T>): Boolean {
        return wrap {
            list.retainAll(elements)
        }
    }

    override fun clear() {
        wrap {
            if (list.isNotEmpty()) {
                list.clear()
                true
            } else {
                false
            }
        }
    }

    protected fun <R> wrap(action: () -> R): R {
        val flag = action()
        if (flag != false) {
            emit()
        }
        return flag
    }

    protected open fun emit() {
        emitted = false
        subject.onNext(this)
    }

    protected open fun observable(): Observable<out Collection<T>> {
        return subject
    }

}